package com.cw.DesignModel23.Structural.ProxyPattern.动态代理;

import com.cw.DesignModel23.Structural.ProxyPattern.静态代理.IOrderService;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 订单服务动态代理类
 *
 * 动态的代理类使用流程 :
 *      1. 内部持有 目标对象
 *      2. 创建动态代理类 , 调用 Proxy.newProxyInstance 创建动态代理类
 *          系统会自动创建一个类 , 该类实现了目标对象的所有接口的所有方法
 *          最后返回一个该动态代理类的实例对象
 *      3. 调用动态代理类实例对象的某个接口方法 , 会自动回调 动态代理类的 invoke 函数
 *              注意 : 被代理的方法必须是 目标对象 的接口中的方法
 */
public class OrderServiceDynamicProxy implements InvocationHandler {
    private Object target;

    public OrderServiceDynamicProxy(IOrderService iOrderService) {
        this.target = iOrderService;
    }

    /**
     * 绑定方法
     *      将目标对象与动态代理类进行绑定
     */
    public Object bind() {
        // 拿到目标对象的类
        Class clazz = target.getClass();
        // 动态代理类时系统执行的时候自动生成的类 , 该类自动实现了指定的接口
        //      动态代理类会获取目标对象的所有接口 , 并实现所有的接口中的所有的方法
        //      该动态代理类 代理的是 target 的接口的方法 , 即 IOrderService 接口的方法
        //      凡是调用创建的动态代理实例对象中的 IOrderService 接口方法 , 都会触发该类的 invoke 方法
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }

    /**
     * 调用代理类的 IOrderService 接口方法 , 就会自动回调该方法
     *      注意 : 所有的 IOrderService 接口方法 , 都会回调该方法
     *            在回调时 , 需要判定一下 , 是哪个方法回调的 , 过滤掉不需要加强的方法
     *
     * @param proxy 该参数几乎用不到
     * @param method 要被增强的方法对象
     * @param args 要被增强的方法对象的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        beforeMethod();

        // 调用目标对象的 method 方法
        Object object = method.invoke(target, args);

        afterMethod();
        return object;
    }

    /**
     * 在被代理对象方法之前执行的内容
     */
    private void beforeMethod() {
        System.out.println("动态代理 OrderServiceStaticProxy 执行 saveOrder 之前");
    }

    /**
     * 在被代理对象方法之后执行的内容
     */
    private void afterMethod() {
        System.out.println("动态代理 OrderServiceStaticProxy 执行 saveOrder 之后");
    }

}

